//
//
//
let vsSource = `
    attribute vec4 a_Position;
    attribute vec4 a_Normal;
    uniform mat4 u_MvpMatrix;
    uniform mat4 u_NormalMatrix;
    uniform vec4 u_Color;
    varying vec4 v_Color;

    void main() {        
        gl_Position = u_MvpMatrix * a_Position;
        vec3 lightDirection = normalize(vec3(0.0, 0.5, 0.7));        
        vec3 normal = normalize((u_NormalMatrix * a_Normal).xyz);
        float nDotL = max(dot(normal, lightDirection), 0.0);
        v_Color = vec4(u_Color.rgb * nDotL + vec3(0.1), 1.0);
    }
`;

let fsSource = `
    precision mediump float;
    varying vec4 v_Color;
    void main() {
        gl_FragColor = v_Color;
    }
`;

let gl;
let d = {}

let g_armAngle = 90.0;
let ANGLE_STEP = 3.0;
let g_jointAngle = 45.0;
let g_joint2Angle = 0.0;
let g_joint3Angle = 0.0
let g_matrixStack = [];
//
function main() {
    gl = initGL("canvas_1");
    if(!gl){
        return
    }

    document.onkeydown = keyDown

    initUI();
    initProgramInfo();
    initBuffer();
    setUpMatrix();
    drawScene();
}

//
function initUI() {
    console.log("initUI -> ");
    webglLessonsUI.setupSlider("#rotation0", {
        value: 0,
        slide: function(event,ui) {
            g_jointAngle = ui.value;
            console.log("drawScene() -> g_jointAngle",g_jointAngle);
            drawScene()
        },
        
        min: -180,
        max: 180,
    });
    webglLessonsUI.setupSlider("#rotation1", {
        value: g_armAngle,
        slide: function(event,ui) {
            console.log("drawScene() -> g_armAngle",g_armAngle);
            g_armAngle = ui.value;
            drawScene()
        },
        min: -180,
        max: 180,
    });
    webglLessonsUI.setupSlider("#rotation2", {
        value: g_joint2Angle,
        slide: function(event,ui) {
            console.log("drawScene() -> g_joint2Angle",g_joint2Angle);
            g_joint2Angle = ui.value;
            drawScene()
        },
        min: -180,
        max: 180,
    });
    webglLessonsUI.setupSlider("#rotation3", {
        value: g_joint3Angle,
        slide: function(event,ui) {
            console.log("drawScene() -> g_joint2Angle",g_joint3Angle);
            g_joint3Angle = ui.value;
            drawScene()
        },
        min: -180,
        max: 180,
    });
}

function setUpMatrix(){

    let viewProjMatrix = new Matrix4();
    viewProjMatrix.setPerspective(50,gl.canvas.width/gl.canvas.height,1.0,1000.0);
    viewProjMatrix.lookAt(20,10,30,0,0,0,0,1,0);
    d.viewProjMatrix = viewProjMatrix;


    d.modelMatrix = new Matrix4();
    d.mvpMatrix = new Matrix4();
    d.normalMatrix = new Matrix4();
    
    gl.enable(gl.DEPTH_TEST);
    gl.clearColor(0.6,0.6,0.6,1.0);
}

function initBuffer() {
    console.log("initBuffer -> ");
 
    var vertices = new Float32Array([
        0.5, 1.0, 0.5, -0.5, 1.0, 0.5, -0.5, 0.0, 0.5,  0.5, 0.0, 0.5, // v0-v1-v2-v3 front
        0.5, 1.0, 0.5,  0.5, 0.0, 0.5,  0.5, 0.0,-0.5,  0.5, 1.0,-0.5, // v0-v3-v4-v5 right
        0.5, 1.0, 0.5,  0.5, 1.0,-0.5, -0.5, 1.0,-0.5, -0.5, 1.0, 0.5, // v0-v5-v6-v1 up
       -0.5, 1.0, 0.5, -0.5, 1.0,-0.5, -0.5, 0.0,-0.5, -0.5, 0.0, 0.5, // v1-v6-v7-v2 left
       -0.5, 0.0,-0.5,  0.5, 0.0,-0.5,  0.5, 0.0, 0.5, -0.5, 0.0, 0.5, // v7-v4-v3-v2 down
        0.5, 0.0,-0.5, -0.5, 0.0,-0.5, -0.5, 1.0,-0.5,  0.5, 1.0,-0.5  // v4-v7-v6-v5 back
      ]);
    
      // Normal
      var normals = new Float32Array([
        0.0, 0.0, 1.0,  0.0, 0.0, 1.0,  0.0, 0.0, 1.0,  0.0, 0.0, 1.0, // v0-v1-v2-v3 front
        1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0, // v0-v3-v4-v5 right
        0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0, // v0-v5-v6-v1 up
       -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
        0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0, // v7-v4-v3-v2 down
        0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0  // v4-v7-v6-v5 back
      ]);
    
      // Indices of the vertices
      var indices = new Uint8Array([
         0, 1, 2,   0, 2, 3,    // front
         4, 5, 6,   4, 6, 7,    // right
         8, 9,10,   8,10,11,    // up
        12,13,14,  12,14,15,    // left
        16,17,18,  16,18,19,    // down
        20,21,22,  20,22,23     // back
      ]);

      gl.bindBuffer(gl.ARRAY_BUFFER, null);

      let positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);


      let normalBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER,normalBuffer);
      gl.bufferData(gl.ARRAY_BUFFER,normals,gl.STATIC_DRAW);


      let indexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);

      let buffers = {
          position: positionBuffer,
          normals:normalBuffer,
          indices:indexBuffer,
      }
      d.buffers = buffers;

}
// 
function initProgramInfo() {

    const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
    let programInfo =  {
        program:shaderProgram,
        attribLocations: {
            vertexPosition:gl.getAttribLocation(shaderProgram,'a_Position'),
            normalPosition:gl.getAttribLocation(shaderProgram,'a_Normal'),
           
        },
        uniformLocations : {
            mvpMatrix:gl.getUniformLocation(shaderProgram,"u_MvpMatrix"),
            normalMatrix:gl.getUniformLocation(shaderProgram,'u_NormalMatrix'),
            colorPosition:gl.getUniformLocation(shaderProgram,"u_Color"),
        }
    }
    d.programInfo = programInfo
}
// 
function drawScene(){
   
    gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);

    // 
    let baseHeight = 2;
    d.modelMatrix.setTranslate(0.0,-12.0,0.0);
    drawBox(10.0,baseHeight,10.0)
   


    let armLength = 10.0;
    d.modelMatrix.translate(0,baseHeight,0);
    d.modelMatrix.rotate(g_armAngle,0,1,0);
    drawBox(3,armLength,3.0)

    let arm2Length = 10.0
    d.modelMatrix.translate(0,armLength,0);
    d.modelMatrix.rotate(g_jointAngle,0,0,1.0);
    drawBox(4,arm2Length,4);

    let palmLength = 2.0;
    d.modelMatrix.translate(0,arm2Length,0.0);
    d.modelMatrix.rotate(g_joint2Angle,0,1.0,0.0);
    drawBox(2,palmLength,6);
    d.modelMatrix.translate(0,palmLength,0);

    pushMatrix(d.modelMatrix);
    d.modelMatrix.translate(0,0,2);
    d.modelMatrix.rotate(g_joint3Angle,1.0,0,0);
    drawBox(1.0,2.0,1.0);
    d.modelMatrix = popMatrix();
    

    d.modelMatrix.translate(0,0,-2.0);
    d.modelMatrix.rotate(-g_joint3Angle,1.0,0.0,0.0);
    drawBox(1.0,2.0,1.0);


    // d.modelMatrix.translate(0,armLength,0);
    // d.modelMatrix.rotate(g_jointAngle,0.0,0.0,1.0);
    // d.modelMatrix.scale(1.3,1.0,1.3);
    // drawBox()


}

function drawBox(width,height,depth){

    gl.useProgram(d.programInfo.program);

    pushMatrix(d.modelMatrix);

    d.modelMatrix.scale(width,height,depth);

    d.mvpMatrix.set(d.viewProjMatrix);
    d.mvpMatrix.multiply(d.modelMatrix);
    gl.uniformMatrix4fv(d.programInfo.uniformLocations.mvpMatrix,false,d.mvpMatrix.elements);

    d.normalMatrix.setInverseOf(d.modelMatrix);
    d.normalMatrix.transpose();
    gl.uniformMatrix4fv(d.programInfo.uniformLocations.normalMatrix,false,d.normalMatrix.elements);

    gl.uniform4fv(d.programInfo.uniformLocations.colorPosition,[0,1,0,0.0])

    gl.bindBuffer(gl.ARRAY_BUFFER, d.buffers.position);
    gl.vertexAttribPointer(d.programInfo.attribLocations.vertexPosition, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(d.programInfo.attribLocations.vertexPosition);

    //normal
    gl.bindBuffer(gl.ARRAY_BUFFER, d.buffers.normals);
    gl.vertexAttribPointer(d.programInfo.attribLocations.normalPosition, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(d.programInfo.attribLocations.normalPosition);


    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, d.buffers.indices);
    gl.drawElements(gl.TRIANGLES,36,gl.UNSIGNED_BYTE,0);
    d.modelMatrix = popMatrix();
}

function keyDown(event){

    let keyCode = event.keyCode;
    // console.log("keyDown -> ",keyCode);
    switch(keyCode){
        case 38:
            if(g_jointAngle < 135.0) {
                g_jointAngle +=ANGLE_STEP;
            }
            break;
        case 40:
            if(g_jointAngle > -135.0){
                g_jointAngle -=ANGLE_STEP;
            }
            break;
        case 39:
            g_armAngle = (g_armAngle +=ANGLE_STEP)% 360;
            break;
        case 37:
            g_armAngle = (g_armAngle -= ANGLE_STEP)% 360;
            break;
     }
     drawScene(); 
}

function pushMatrix(m){
    var m2 = new Matrix4(m);
    g_matrixStack.push(m2);
}

function popMatrix(){
    return g_matrixStack.pop();
}